package com.org.redis.limit;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class LimiterHandler {

    @Resource
    private RedisTemplate<String,Integer> redisTemplate;

    @Pointcut("@annotation(com.org.redis.limit.Limiter)")
    public void limiter(){}

    /**
    private DefaultRedisScript<Long> getRedisScript;

    @PostConstruct
    public void init() {
        getRedisScript = new DefaultRedisScript<>();
        getRedisScript.setResultType(Long.class);
        getRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/limiter.lua")));
        System.out.println("lua脚本加载完成");
    }
    **/

    @Around("limiter()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature(); //获取调用的方法

        //获取注解
        Method method = point.getTarget().getClass().getMethod(signature.getName(), signature.getMethod().getParameterTypes());
        Limiter limiter = method.getAnnotation(Limiter.class);
        String value = limiter.value();
        long request = limiter.request();
        long expire = limiter.expire();
        
        if(value == ""){
            return point.proceed();
        }

        //根据key获取已请求次数
        Integer maxTimes = redisTemplate.opsForValue().get(value);
        if(maxTimes == null){
            //set时一定要加过期时间
            redisTemplate.opsForValue().set(value, 1, expire, TimeUnit.SECONDS);
        }else if(maxTimes < request){
            Long expire1 = redisTemplate.boundValueOps(value).getExpire();
            redisTemplate.opsForValue().set(value, maxTimes+1, expire1, TimeUnit.SECONDS);
        }else{
            StringBuffer sb = new StringBuffer();
            String msg = sb.append("超过单位时间=").append(expire).append("允许的请求次数=").append(request).append("[触发限流]").toString();
            return msg;
        }

        //执行原方法
        return point.proceed();

        //执行lua脚本
//        List<String> keyList = Lists.newArrayList();
//        keyList.add(value);
//
//        Long result = (Long) redisTemplate.execute(getRedisScript, keyList, expire, request);
//
//        StringBuffer sb = new StringBuffer();
//        if ((result == 0)) {
//            String msg = sb.append("超过单位时间=").append(expire).append("允许的请求次数=").append(request).append("[触发限流]").toString();
//            return msg;
//        }
//        //执行原方法
//        return point.proceed();

    }


}
